﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernateToSQLMapping.DAL;
using System.Data;
using NHibernateToSQLMapping.Factory;
using NHibernateToSQLMapping.Entity;

namespace NHibernateToSQLMapping.BLL
{
    public class MasterBLL
    {
        public string path = "C:\\Users\\Administrator\\Desktop\\";
        public string _namespace = "NHibernate.Entity";
        public string _assembly = "NHibernate.Entity";
        public string _serverType = "SQL Server 2008";
        public MasterBLL(string _serverType)
        {
            if (!string.IsNullOrEmpty(_serverType))
                this._serverType = _serverType;
        }

        public MasterBLL(string _serverType, string path, string _namespace, string _assembly)
        {
            if (!string.IsNullOrEmpty(_serverType))
                this._serverType = _serverType;
            if (!string.IsNullOrEmpty(path))
                this.path = path;
            if (!string.IsNullOrEmpty(_namespace))
                this._namespace = _namespace;
            if (!string.IsNullOrEmpty(_assembly))
                this._assembly = _assembly;
        }

        /// <summary>
        /// 查询数据库名
        /// </summary>
        /// <param name="conStr">连接字符串</param>
        /// <returns></returns>
        public List<string> GetDataBaseName(string conStr)
        {
            MasterFactory factory = new MasterFactory();
            IMasterDAL dal = factory.CreateDAL(_serverType);
            return dal.GetDataBaseName(conStr);
        }

        /// <summary>
        /// 查询所有表名
        /// </summary>
        /// <param name="conStr">连接字符串</param>
        /// <returns></returns>
        public List<string> GetTableName(string conStr)
        {
            MasterFactory factory = new MasterFactory();
            IMasterDAL dal = factory.CreateDAL(_serverType);
            return dal.GetTableName(conStr);
        }

        /// <summary>
        /// 查询所有视图名
        /// </summary>
        /// <param name="conStr">连接字符串</param>
        /// <returns></returns>
        public List<string> GetViewName(string conStr)
        {
            MasterFactory factory = new MasterFactory();
            IMasterDAL dal = factory.CreateDAL(_serverType);
            return dal.GetViewName(conStr);
        }

        /// <summary>
        /// 生成文件
        /// </summary>
        /// <param name="conStr"></param>
        /// <param name="list"></param>
        public bool CreateFile(string conStr, List<string> list, bool isDistinct, bool isPascal, bool isCreateXML, bool isCreateSQL)
        {
            foreach (string tableName in list)
            {
                CreateTableInfo(conStr, tableName, isDistinct, isPascal, isCreateXML, isCreateSQL);
            }
            return true;
        }

        /// <summary>
        /// 查询所有字段属性
        /// </summary>
        /// <param name="conStr">连接字符串</param>
        /// <returns></returns>
        private void CreateTableInfo(string conStr, string tableName, bool isDistinct, bool isPascal, bool isCreateXML, bool isCreateSQL)
        {
            MasterFactory factory = new MasterFactory();
            IMasterDAL dal = factory.CreateDAL(_serverType);
            DataSet ds = dal.GetTableInfo(conStr, tableName);
            CreatetCSContents(ds, isDistinct, isPascal);
            if (isCreateXML)
            {
                CreatetXMLContents(ds, isPascal);
            }
            if (isCreateSQL)
            {
                CreatetSQLContents(ds, isPascal);
            }
        }

        /// <summary>
        /// 生成实体文件
        /// </summary>
        /// <returns></returns>
        private void CreatetCSContents(DataSet ds, bool isDistinct, bool isPascal)
        {
            if (ds != null)
            {
                TableProperty tableProperty = new TableProperty();
                StringBuilder cs = new StringBuilder();
                tableProperty.TableName = ds.Tables[0].Rows[0][0].ToString();
                tableProperty.TableRemarks = ds.Tables[0].Rows[0][1].ToString();
                DataRow[] drs = ds.Tables[1].Select("IsPrimarykey='1'");
                if (drs != null && drs.Count() > 0)
                {
                    tableProperty.IsKey = true;
                }
                else
                {
                    tableProperty.IsKey = false;
                }
                cs.AppendLine("using System;");
                cs.AppendLine("using System.Collections.Generic;");
                cs.AppendLine("using System.Linq;");
                cs.AppendLine("using System.Text;");
                cs.AppendLine("namespace " + _assembly);
                cs.AppendLine("{");
                cs.AppendLine("    /// <summary>");
                cs.AppendLine("    /// " + tableProperty.TableRemarks);
                cs.AppendLine("    /// </summary>");
                cs.AppendLine("    [Serializable]");



                if (isDistinct)
                {
                    cs.AppendLine(string.Format("    public class {0} : IEquatable<{0}>", tableProperty.TableName));
                }
                else
                {
                    cs.AppendLine("    public class " + tableProperty.TableName);
                }
                cs.AppendLine("    {");
                cs.AppendLine("        public " + tableProperty.TableName + "() { }");
                for (int i = 0; i < ds.Tables[1].Rows.Count; i++)
                {
                    FiledProperty filedProperty = new FiledProperty();
                    DataRow dr = ds.Tables[1].Rows[i];
                    filedProperty.FiledName = dr["ColumnName"].ToString();
                    if (isPascal)
                    {
                        filedProperty.FiledName = ToTitleCase(filedProperty.FiledName);
                    }
                    filedProperty.FiledType = dr["DataType"].ToString();
                    filedProperty.FiledRemarks = dr["Description"].ToString();
                    filedProperty.IsPrimarykey = dr["IsPrimarykey"].ToString();
                    filedProperty.IsIdentity = dr["IsIdentity"].ToString();
                    cs.AppendLine("        /// <summary>");
                    cs.AppendLine("        /// " + filedProperty.FiledRemarks);
                    cs.AppendLine("        /// </summary>");
                    cs.AppendLine("        public " + filedProperty.FiledType + " " + filedProperty.FiledName + " { get; set; }");
                }
                if (isDistinct)
                {
                    cs.AppendLine(GetDistinctStr(drs, tableProperty.TableName, isPascal));
                }
                cs.AppendLine("    }");
                cs.AppendLine("}");

                Comm.FileDeliver file = new Comm.FileDeliver();
                file.CreateFile(path + tableProperty.TableName + ".cs", cs.ToString());
            }
        }

        /// <summary>
        /// 生成XML文件
        /// </summary>
        /// <returns></returns>
        private void CreatetXMLContents(DataSet ds, bool isPascal)
        {
            if (ds != null)
            {
                TableProperty tableProperty = new TableProperty();
                StringBuilder xml = new StringBuilder();
                tableProperty.TableName = ds.Tables[0].Rows[0][0].ToString();
                tableProperty.TableRemarks = ds.Tables[0].Rows[0][1].ToString();
                xml.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
                xml.AppendLine("<hibernate-mapping xmlns=\"urn:nhibernate-mapping-2.2\" assembly=\"" + _assembly + "\" namespace=\"" + _namespace + "\">");
                xml.AppendLine("  <class name=\"" + tableProperty.TableName + "\" table=\"" + tableProperty.TableName + "\">");

                DataRow[] drs = ds.Tables[1].Select("IsPrimarykey='1'");
                if (drs != null && drs.Count() > 0)
                {
                    tableProperty.IsKey = true;
                    xml.Append(GetIdStr(drs, isPascal));
                }
                else
                {
                    tableProperty.IsKey = false;
                }
                for (int i = 0; i < ds.Tables[1].Rows.Count; i++)
                {
                    FiledProperty filedProperty = new FiledProperty();
                    DataRow dr = ds.Tables[1].Rows[i];
                    filedProperty.FiledName = dr["ColumnName"].ToString();
                    filedProperty.FiledNamePascal = filedProperty.FiledName;
                    if (isPascal)
                    {
                        filedProperty.FiledNamePascal = ToTitleCase(filedProperty.FiledNamePascal);
                    }
                    filedProperty.FiledType = dr["DataType"].ToString();
                    filedProperty.FiledRemarks = dr["Description"].ToString();
                    filedProperty.IsPrimarykey = dr["IsPrimarykey"].ToString();
                    filedProperty.IsIdentity = dr["IsIdentity"].ToString();
                    if (i == 0)
                    {
                        if (!tableProperty.IsKey)
                        {
                            xml.AppendLine("    <id name=\"" + filedProperty.FiledName + "\" column=\"" + filedProperty.FiledNamePascal + "\">");
                            if (filedProperty.IsIdentity == "1")
                            {
                                xml.AppendLine("        <generator class=\"native\"></generator>");
                            }
                            xml.AppendLine("    </id>");
                        }
                    }
                    else
                    {
                        xml.AppendLine("    <property name=\"" + filedProperty.FiledName + "\" column=\"" + filedProperty.FiledNamePascal + "\"/>");
                    }
                }
                xml.AppendLine("  </class>");
                xml.AppendLine("</hibernate-mapping>");
                Comm.FileDeliver file = new Comm.FileDeliver();
                file.CreateFile(path + tableProperty.TableName + ".hbm.xml", xml.ToString());
            }
        }

        /// <summary>
        /// 生成SQL文件
        /// </summary>
        /// <returns></returns>
        private void CreatetSQLContents(DataSet ds, bool isPascal)
        {
            if (ds != null)
            {
                TableProperty tableProperty = new TableProperty();
                StringBuilder sql = new StringBuilder();
                tableProperty.TableName = ds.Tables[0].Rows[0][0].ToString();
                string flag = "";
                sql.Append("SELECT ");
                for (int i = 0; i < ds.Tables[1].Rows.Count; i++)
                {
                    FiledProperty filedProperty = new FiledProperty();
                    DataRow dr = ds.Tables[1].Rows[i];
                    filedProperty.FiledName = dr["ColumnName"].ToString();
                    string filename = "";
                    if (isPascal)
                    {
                        filename = ToTitleCase(filedProperty.FiledName) + "=";
                    }
                    sql.AppendFormat("{2}{1}{0}", filedProperty.FiledName, filename, flag);
                    flag = ",";
                }
                sql.AppendFormat(" FROM dbo.{0}", tableProperty.TableName);
                Comm.FileDeliver file = new Comm.FileDeliver();
                file.CreateFile(path + tableProperty.TableName + ".sql", sql.ToString());
            }
        }

        /// <summary>
        /// 主键xml生成
        /// </summary>
        /// <param name="drs"></param>
        /// <returns></returns>
        public string GetIdStr(DataRow[] drs, bool isPascal)
        {
            StringBuilder sb = new StringBuilder();
            if (drs.Count() > 1)
            {
                var ids = drs;
                sb.AppendLine("    <composite-id>");
                foreach (DataRow c in ids)
                {
                    string fileName = c["ColumnName"].ToString();
                    string filedNamePascal = fileName;
                    if (isPascal)
                    {
                        filedNamePascal = ToTitleCase(fileName);
                    }
                    sb.AppendLine("        <key-property name=\"" + fileName + "\" column=\"" + filedNamePascal + "\" />");
                }
                sb.AppendLine("    </composite-id>");
            }
            else
            {
                FiledProperty filedProperty = new FiledProperty();
                filedProperty.FiledName = drs[0]["ColumnName"].ToString();
                filedProperty.FiledNamePascal = filedProperty.FiledName;
                if (isPascal)
                {
                    filedProperty.FiledNamePascal = ToTitleCase(filedProperty.FiledNamePascal);
                }
                filedProperty.FiledType = drs[0]["DataType"].ToString();
                filedProperty.FiledRemarks = drs[0]["Description"].ToString();
                filedProperty.IsIdentity = drs[0]["IsIdentity"].ToString();
                sb.AppendLine("    <id name=\"" + filedProperty.FiledName + "\" column=\"" + filedProperty.FiledNamePascal + "\">");
                if (filedProperty.IsIdentity == "1")
                {
                    sb.AppendLine("        <generator class=\"native\"></generator>");
                }
                sb.AppendLine("    </id>");
            }
            return sb.ToString();
        }

        /// <summary>
        /// 去重方法代码生成
        /// </summary>
        /// <param name="drs"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public string GetDistinctStr(DataRow[] drs, string tableName, bool isPascal)
        {
            StringBuilder cs = new StringBuilder();
            StringBuilder sb = new StringBuilder();
            cs.AppendLine("        /// <summary>");
            cs.AppendLine("        /// ");
            cs.AppendLine("        /// </summary>");
            cs.AppendLine(string.Format("        public bool Equals({0} other)", tableName));
            cs.AppendLine("        {");
            cs.AppendLine("            if (Object.ReferenceEquals(other, null)) return false;");
            cs.AppendLine("            if (Object.ReferenceEquals(this, other)) return true;");
            cs.Append("            return ");

            sb.AppendLine("        /// <summary>");
            sb.AppendLine("        /// ");
            sb.AppendLine("        /// </summary>");
            sb.AppendLine("        public override int GetHashCode()");
            sb.AppendLine("        {");
            sb.Append("            return ");

            string flag0 = "";
            string flag1 = "";
            foreach (DataRow c in drs)
            {
                string fileName = c["ColumnName"].ToString();
                if (isPascal)
                {
                    fileName = ToTitleCase(fileName);
                }

                cs.Append(string.Format("{1}{0}.Equals(other.{0})", fileName, flag0));

                sb.Append(string.Format("{1}({0} == null ? 0 : {0}.GetHashCode())", fileName, flag1));
                flag0 = "&&";
                flag1 = "^";
            }
            cs.AppendLine(";");
            sb.AppendLine(";");

            cs.AppendLine("        }");
            sb.AppendLine("        }");
            return cs.ToString() + sb.ToString();
        }

        /// <summary>
        /// 首字母大写
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public string ToTitleCase(string str)
        {
            if (!string.IsNullOrEmpty(str))
            {
                if (str.Length > 2)
                {
                    if (str[1] == char.ToUpper(str[1]))
                    {
                        return str.Substring(1);
                    }
                }
                if (str.Length > 1)
                {
                    return char.ToUpper(str[0]) + str.Substring(1);
                }
                return char.ToUpper(str[0]).ToString();
            }
            return null;
            //return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(str);
        }
    }
}
